Javascript Event Loop with Node.js for Beginners

Understanding how Node.js works is often difficult for beginners. Some popular questions are: What is “single-threaded”? What is “non-blocking”? What is “asynchronous”? What is “event loop” ? In this post, I will be making those ambiguous things clearer. We are not going to dive too deeply into low level details. Instead, I am going explain how Node.js works by looking at key mechanisms surrouding concept of “Event Loop”, which will hopefully give beginners a good start on their journey with Node.js.

What is JavaScript Event Loop?

Event loop in Node.js is actually a part of JavaScript, the language used by Node.js. We can see event loop in both front-end and back-end work. In Node.js, event loop is important, but it is not alone. To understand how it works, we need to put it into a bigger pictures, where there are other components: Stack, Queue, and WebAPIs/C APIs as in the following diagram:

JavaScript Event Loop

1. To understand this diagram, let’s take a look at a front-end example.

1
2
3
4
5
6
7
console.log('How');

setTimeout(function callback() {
console.log('are');
}, 3000);

console.log('you?');

The result is:

1
2
3
How
you?
are

So, what happened under the hood ?

  • Step 1: console.log.log('How') is put into stack, print out How, then finishes. The stack is then empty.
  • Step 2:
    setTimeout(function callback() { console.log('are'); }, 3000); is put into stack. It sends a request to webAPI, and then is popped out of stack. Stack is then again empty.
  • Step 3: console.log.log('you?') is put into stack, print out you?, then finishes. The stack is then empty.
  • Step 4: 3000 millisecond after request in step 2 was sent, the callback() { console.log('are'); } is sent to the queue, then back to the stack, prints out are. Then the stack is empty again.

The important things happen here : The statement (console.log('you?');) will be executed without waiting for 3000 milliseconds. The work done within such 3 seconds is handled inside webAPIs, which is outside of current the thread running JavasCript code, so it will not block the current thread for 3 seconds. This is why Node.js is non-blocking. When the work is done, it will send the callback() { console.log('are'); } to the queue (enqueue). We can consider such a callback as an event. Callbacks in the queue will one-by-one be enqueued and move to the stack with the condition that a callback in the queue can enter the stack only when stack is empty. In this case, the event loop get an event (callback) from the queue, and push such a callback to the stack. This mechanism ensures the single-threaded property of JavaScript. Single threaded means JavaScript engine (V8) executes one thing at a time. Using stack, JavaSript is able to execute one thing at a time in a single thread (How stack works with function calls is explained here Stack call )

2. How about Node.js? How does it work with the above diagram?

The main idea is generally similar. A slightly different point is that: Node.js use C APIs such libuv instead of WebAPIS. Libuv abstracts way of underlying network and files system function. Another important point is that a new request from user coming in is one kind of event, which means that it will be in the queue before going to the stack as usual event.

So, what to remember?

  • JavaScript code runs in a single-threaded way (one at a time).
  • Heavy work (such as I/O) will be given out to other “guys” (WebAPIs, C APIs) to handle. When such guys finish their jobs, they push the results (notifications) to the queue, then to the stack, ensuring that JavaScript code runs in a single-threaded way. By giving heavy work to such guys and keep running JavaScript code, Node.js can handle multiples requests almost concurrently because JavaScript code runs a lot faster than I/O work. The request n+1 will be handled right after JavaScript code of request n finishes running (heavy work is now being handled outside the current thread), which is very fast, thus making these 2 requests seem to run concurrently.

What to remember